#region Using Statements
using System;
using System.IO;
using System.Collections.Generic;
using System.Collections;
using System.Reflection;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Storage;
using XDebugConsole.Components;


#endregion

namespace XDebugConsole
{

    public class DebugConsole : DrawableGameComponent
    {
        private List<DebugComponent> components;

        // Some shared resources between every DebugComponent
        public DebugSharedResources resources;

        //private VertexPositionColor[] lines;
        public int lineCount;

        // Some general debugging variables
        private int drawCount;
        private int updateCount;

        // Components
        private TreeView treeView;
        private Marker marker;
        private Alerter alerter;
        private LineDrawer lineDrawer;

        #region Constructor
        public DebugConsole(IContainGameInfo gameInfo)
            : base(gameInfo.Game)
        {
            this.resources = new DebugSharedResources();
            this.components = new List<DebugComponent>();
            resources.gameInfo = gameInfo;
            resources.device = gameInfo.Game.GraphicsDevice;
            resources.spriteBatch = new SpriteBatch(resources.device);
            

            //String pathPrefix = "";
            //resources.content = new ContentManager(gameInfo.Game.Services, "Content");
            resources.content = new ResourceContentManager(gameInfo.Game.Services, Resource1.ResourceManager);
            resources.font = resources.content.Load<SpriteFont>("Default");
            resources.fontTiny = resources.content.Load<SpriteFont>("Tiny");
            resources.fontAlert = resources.content.Load<SpriteFont>("Alert");
            //this.cursorTexture = resources.content.Load<Texture2D>("Textures\\cursor");
            resources.effect = new BasicEffect(resources.device, null);

            this.treeView = new TreeView(resources);
            this.marker = new Marker(resources);
            this.alerter = new Alerter(resources);
            this.lineDrawer = new LineDrawer(resources);
            this.components.Add(treeView);
            this.components.Add(marker);
            this.components.Add(alerter);
            this.components.Add(lineDrawer);

            //this.lines = new VertexPositionColor[1000];
            resources.vertexDeclaration = new VertexDeclaration(gameInfo.Game.GraphicsDevice,
                VertexPositionColor.VertexElements);

            this.DrawOrder = Int32.MaxValue - 1;
            //this.Execute("trace Debug.DrawCount", drawCount);
            //this.Execute("trace Debug.UpdateCount", updateCount);
        }
        #endregion

        #region Execute
        /// <summary>
        /// Executes a command.
        /// </summary>
        /// <param name="command">The command with all its string arguments.</param>
        /// <param name="arguments">Any non-string argument if needed.</param>
        public void Execute(String command, params object[] arguments)
        {
            String[] tokens = command.Split(' ');
            tokens[0] = tokens[0].ToLowerInvariant();

            foreach (DebugComponent component in components)
            {
                if (component.HandlesCommand(tokens[0]))
                {
                    component.Execute(tokens, arguments);
                }
            }
        }
        /// <summary>
        /// Executes a command.
        /// </summary>
        /// <param name="command">The command with all its string arguments.</param>
        public void Execute(String command)
        {
            Execute(command, null);
        }
        #endregion

        #region Wrapper functions
        public void ShowMark(String key, Vector3 position, Color color)
        {
            this.marker.ShowMark(key, position, color);
        }
        public void ShowMark(String key, Vector3 position)
        {
            this.marker.ShowMark(key, position);
        }

        public void Alert(Object message)
        {
            this.alerter.alert(message);
        }
        public void ShowLine(String key, Vector3 v1, Vector3 v2)
        {
            lineDrawer.ShowLine(key, v1, v2);
        }
        public void ShowLine(String key, Vector3 v1, Vector3 v2, Color color)
        {
            lineDrawer.ShowLine(key, v1, v2, color);
        }
        #endregion

        #region Draw
        public override void Draw(GameTime gameTime)
        {
            drawCount++;
            foreach (DebugComponent component in components)
            {
                component.Draw(gameTime);
            }
        }
        #endregion

        #region Update
        public override void Update(GameTime gameTime)
        {
            foreach (DebugComponent component in components)
            {
                component.Update(gameTime);
            }
            updateCount++;
            //this.Execute("trace Debug.UpdateCount", updateCount);
            //this.Execute("trace Debug.DrawCount", drawCount);

            //DebugMouse.Update(gameTime);
            //if (DebugMouse.LeftJustPressed)
            //    treeView.LeftClick(DebugMouse.Position);

            base.Update(gameTime);
        }
        #endregion

    }
}
